package com.athuahua.streamAPI;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.junit.Test;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Author: huahua
 * @Date: 2024/10/24 0024
 * @Time: 17:02
 * @Description:
 */
public class StreamDemo {
    @Test
    public void test01() {
        //需求，是个元素，挑出最大偶数
        List<Integer> list = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        //for循环，挨个遍历找到偶数，下次找到的偶数和临时变量比较最后找到最大的
        //...

        //流特性
        //1).流是lazy的，只有有终止操作，其中的中间操作才会进行计算

        //streamAPI三步走
        //1.数据封装成流 集合类.stream
        //2.定义流式操作
        //3.获取最终结果

        //intermediate operation 中间操作【可以有一系列】
        //terminal operation 终止操作 【只能有一个】
        list.stream()
                .filter(ele -> ele % 2 == 0) // 过滤我们想要的，如果断言返回true就是我们要的
                .max(Integer::compareTo) // Optional 防空指针异常
                .ifPresent(System.out::println); //如果存在就打印
        ;


        List aaa = new ArrayList<>();
        List<Object> objectList = Collections.synchronizedList(new ArrayList<>());

        //流的所有操作都是无状态，数据状态仅在此函数内有效，不溢出
        System.out.println("主线程: " + Thread.currentThread());
        long count = Stream.of(1, 2, 3, 4, 5)
                .parallel() //并发流
                .filter(i -> {
                    System.out.println("filter线程: " + Thread.currentThread() + " 正在执行: " + i);
                    //aaa.add(i); 这种行为称为有状态数据，有状态数据将产生并发安全问题，千万不要这么写
                    //objectList.add(i); 如果非要这么做 . 加锁，或者使用线程安全的方式
                    return i > 2;
                }) //中间操作
                .count();//终止操作
        System.out.println(count);

    }

    //① 数据流
    @Test
    public void test02() {

        //1.创建流
        Stream<Integer> stream = Stream.of(1, 2, 3);
        Stream<Integer> concat = Stream.concat(Stream.of(2, 3, 4), stream); //合并
        Stream<Object> build = Stream.builder().add("11").add("22").add("33").build();

        //2.集合中获取流
        List<Integer> integers = List.of(1, 2, 3);
        Stream<Integer> stream1 = integers.stream();

        Map<Object, Object> of = Map.of();
        of.keySet().stream();
        of.values().stream();

    }

    //②中间操作
    @Test
    public void test03() {
        @Data
        @NoArgsConstructor
        @AllArgsConstructor
        class Person {
            private String name;
            private String gender;
            private Integer age;
        }
        var list = List.of(
                new Person("zhang san", "男", 13),
                new Person("li si", "男", 20),
                new Person("wang wu", "男", 22),
                new Person("lao liu", "男", 33),
                new Person("wang qi", "女", 19)
        );

        //年龄 > 18 拿到集合流其实就是拿到集合的深拷贝的值，流的所以操作都是流的元素引用
        //filter
        list.stream()
                .filter(person -> person.age > 18) //挑出年龄>18
                .limit(3) //限额
                .peek(System.out::println) //查看元素
                .map(person -> person.name)        //只需要名字
                .flatMap(ele -> {
                    String[] s = ele.split(" ");
                    return Arrays.stream(s);
                }) //对姓名进行处理，把姓和名拆出来
                .distinct() //去重
                .sorted(String::compareTo) //排序
                .forEach(System.out::println);
        System.out.println("=====================");

        Map<String, List<Person>> collect1 = list.stream()
                .filter(s -> s.age > 15)
                .collect(Collectors.groupingBy(t -> t.gender)); //分组

        System.out.println(collect1);


        System.out.println("=====================");


        List<Integer> collect = List.of(1, 2, 3, 4, 5, 6)
                .stream()
                .filter(i -> i > 2) //无条件遍历流中的每一个元素
                .collect(Collectors.toList());
        System.out.println(collect);


        List<Integer> list1 = List.of(1, 2, 3, 4, 5, 6)
                .stream()
                .takeWhile(i -> i < 2) //满足条件拿到元素，不满足直接结束流操作
                .toList();
        System.out.println(list1);
    }
}
